package me.hetong.caigou.ui.chessboard;

import javafx.application.Platform;
import javafx.geometry.VPos;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.TextAlignment;
import lombok.Data;
import me.hetong.caigou.entity.Chess;
import me.hetong.caigou.util.FenUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 棋盘CANVAS
 *
 * @author hetong
 */
@Data
public class ChessboardForEdit extends Canvas {

    private GraphicsContext gc;
    private Integer gridSize = 40;// 每个方格的宽高
    private Integer crossPy = 2;// 十字交叉点偏移量
    private Integer crossLength = 8;// 十字交叉点线长度
    private Integer lineWidth = 1;// 默认线宽
    private Integer outLineWidth = 2;// 棋盘外边框线宽
    private Integer outLinePy = 4;// 棋盘外边框偏移量
    private String backgroundColor = "#879569";
    private Image chuheImage = new Image("image/chessboard/ch.png");// 楚河图片
    private Image hanjieImage = new Image("image/chessboard/hj.png");// 汉界图片
    private Image ccImage = new Image("image/chessboard/to.png");// 选中图片
    private Map<String, Image> imageMap = new HashMap<>(36);
    private List<Chess> chessList = new ArrayList<>();
    private double radius = 16;
    private double radiusHalf = radius / 2;
    private Chess click1;// 当前选择的棋子
    private Chess blank;// 当前选择的位置
    private boolean turnRed = true;

    public ChessboardForEdit(int size) {
        this.gridSize = size;
        this.setWidth(gridSize * 9 + gridSize / 2);
        this.setHeight(gridSize * 10 + gridSize / 2);
        this.gc = this.getGraphicsContext2D();

        // 初始化所有棋子
        chessList = FenUtils.fenToChessList(null);
        initImage();

        this.draw();

        this.setOnMouseClicked(event -> {
            if (event.getButton() == MouseButton.PRIMARY) {
                leftClick(event);
            }
        });
    }

    /**
     * 初始化所有棋子图片
     */
    private void initImage() {
        for (Chess chess : chessList) {
            String s = (chess.getType() + chess.getK()).toLowerCase().replace("w", "r");
            String url = "image/chessboard/style/default/" + s + ".png";
            Image image = new Image(url);
            imageMap.put(chess.getType() + chess.getK(), image);
        }
    }

    private void leftClick(MouseEvent event) {
        int m = (int) (event.getX() - gridSize / 2) / gridSize;
        int n = (int) (event.getY() - gridSize / 2) / gridSize;

        Chess c = FenUtils.getChess(chessList, m, n);

        click1 = c == null ? new Chess(m, n) : c;

        this.draw();
    }

    private void setDefault() {
        this.gc.setTextAlign(TextAlignment.CENTER);
        this.gc.setTextBaseline(VPos.CENTER);
        this.gc.setFill(Paint.valueOf("#3d3d3d"));
        this.gc.setStroke(Paint.valueOf("#3d3d3d"));
        Label label = new Label();
        label.setStyle("-fx-font-family: 'Arial'");
        gc.setFont(label.getFont());
    }

    public void draw() {
        this.setDefault();
        Platform.runLater(() -> {
            gc.clearRect(0, 0, this.getWidth(), this.getHeight());
            gc.setFill(Color.valueOf(backgroundColor));
            gc.fillRect(0, 0, this.getWidth(), this.getHeight());

            // 画横线
            for (int i = 0; i <= 9; i++) {
                drawLine(0, i, 8, i);
            }

            // 画竖线
            drawLine(0, 0, 0, 9);
            for (int i = 1; i <= 7; i++) {
                drawLine(i, 0, i, 4);
                drawLine(i, 5, i, 9);
            }
            drawLine(8, 0, 8, 9);

            // 画边框粗线
            drawBoardLine();

            // 画斜线叉
            drawLine(3, 0, 5, 2);
            drawLine(5, 0, 3, 2);
            drawLine(3, 7, 5, 9);
            drawLine(5, 7, 3, 9);

            // 画十字
            drawCross4(1, 2);
            drawCross4(7, 2);
            drawCross4(2, 3);
            drawCross4(4, 3);
            drawCross4(6, 3);
            drawCross4(2, 6);
            drawCross4(4, 6);
            drawCross4(6, 6);
            drawCross4(1, 7);
            drawCross4(7, 7);
            drawCross2L(0, 3);
            drawCross2L(0, 6);
            drawCross2R(8, 3);
            drawCross2R(8, 6);

            for (int i = 0; i < 9; i++) {
                drawTextTop(i, String.valueOf(i + 1));
            }
            drawTextBottom(0, "九");
            drawTextBottom(1, "八");
            drawTextBottom(2, "七");
            drawTextBottom(3, "六");
            drawTextBottom(4, "五");
            drawTextBottom(5, "四");
            drawTextBottom(6, "三");
            drawTextBottom(7, "二");
            drawTextBottom(8, "一");

            int py = (int) (gridSize / 2 * 9.5);
            double px = gridSize * 1.5;
            gc.drawImage(chuheImage, px, py, gridSize, gridSize);
            gc.drawImage(hanjieImage, (int) (this.getWidth() - gridSize - px), py, gridSize, gridSize);

            if (click1 != null) {
                int cx = (int) (click1.getX() * gridSize + gridSize / 2 * 1.5);
                int cy = (int) (click1.getY() * gridSize + gridSize / 2 * 1.5);
                drawImageCenter(ccImage, cx, cy, gridSize - 2, gridSize - 2);
                setDefault();
            }

            for (Chess li : chessList) {
                Image image = imageMap.get(li.getType() + li.getK());
                drawImageCenter(image, (int) (li.getX() * gridSize + gridSize / 2 * 1.5), (int) (li.getY() * gridSize + gridSize / 2 * 1.5), gridSize, gridSize);
            }

        });
    }

    private void drawImageCenter(Image image, int cx, int cy, int w, int h) {
        gc.drawImage(image, cx - w / 2, cy - h / 2, w, h);
    }

    /**
     * 画直线
     *
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     */
    private void drawLine(int x1, int y1, int x2, int y2) {
        gc.strokeLine(x1 * gridSize + gridSize / 2 * 1.5, y1 * gridSize + gridSize / 2 * 1.5, x2 * gridSize + gridSize / 2 * 1.5, y2 * gridSize + gridSize / 2 * 1.5);
    }

    /**
     * 画棋盘十字
     *
     * @param x
     * @param y
     */
    private void drawCross4(int x, int y) {
        drawCross2L(x, y);
        drawCross2R(x, y);
    }

    /**
     * 画棋盘左半边十字
     *
     * @param x
     * @param y
     */
    private void drawCross2L(int x, int y) {
        // 中心点
        x = x * gridSize + gridSize / 2 + gridSize / 2 / 2;
        y = y * gridSize + gridSize / 2 + gridSize / 2 / 2;

        // 右上
        gc.strokeLine(x + crossPy, y - crossPy, x + crossPy + crossLength, y - crossPy);
        gc.strokeLine(x + crossPy, y - crossPy, x + crossPy, y - crossPy - crossLength);
        // 右下
        gc.strokeLine(x + crossPy, y + crossPy, x + crossPy + crossLength, y + crossPy);
        gc.strokeLine(x + crossPy, y + crossPy, x + crossPy, y + crossPy + crossLength);
    }

    /**
     * 画棋盘右半边十字
     *
     * @param x
     * @param y
     */
    private void drawCross2R(int x, int y) {
        // 中心点
        x = x * gridSize + gridSize / 2 + gridSize / 2 / 2;
        y = y * gridSize + gridSize / 2 + gridSize / 2 / 2;
        // 左上
        gc.strokeLine(x - crossPy, y - crossPy, x - crossPy - crossLength, y - crossPy);
        gc.strokeLine(x - crossPy, y - crossPy, x - crossPy, y - crossPy - crossLength);
        // 左下
        gc.strokeLine(x - crossPy, y + crossPy, x - crossPy - crossLength, y + crossPy);
        gc.strokeLine(x - crossPy, y + crossPy, x - crossPy, y + crossPy + crossLength);
    }

    private void drawTextTop(int x, String text) {
        gc.setFill(Color.valueOf("#3d3d3d"));
        gc.fillText(text, x * gridSize + gridSize / 2 * 1.5, 0 * gridSize + gridSize / 2 * 1.5 - 15);
    }

    private void drawTextBottom(int x, String text) {
        gc.fillText(text, x * gridSize + gridSize / 2 * 1.5, 9 * gridSize + gridSize / 2 * 1.5 + 15);
    }

    private void drawBoardLine() {
        gc.setLineWidth(outLineWidth);
        gc.strokeLine(0 * gridSize + gridSize / 2 * 1.5 - outLinePy, 0 * gridSize + gridSize / 2 * 1.5 - outLinePy, 8 * gridSize + gridSize / 2 * 1.5 + outLinePy, 0 * gridSize + gridSize / 2 * 1.5 - outLinePy);
        gc.strokeLine(0 * gridSize + gridSize / 2 * 1.5 - outLinePy, 0 * gridSize + gridSize / 2 * 1.5 - outLinePy, 0 * gridSize + gridSize / 2 * 1.5 - outLinePy, 9 * gridSize + gridSize / 2 * 1.5 + outLinePy);
        gc.strokeLine(0 * gridSize + gridSize / 2 * 1.5 - outLinePy, 9 * gridSize + gridSize / 2 * 1.5 + outLinePy, 8 * gridSize + gridSize / 2 * 1.5 + outLinePy, 9 * gridSize + gridSize / 2 * 1.5 + outLinePy);
        gc.strokeLine(8 * gridSize + gridSize / 2 * 1.5 + outLinePy, 0 * gridSize + gridSize / 2 * 1.5 - outLinePy, 8 * gridSize + gridSize / 2 * 1.5 + outLinePy, 9 * gridSize + gridSize / 2 * 1.5 + outLinePy);
        gc.setLineWidth(lineWidth);
    }

    public void setClick1(Chess click1) {
        this.click1 = click1;
        draw();
    }

    public void setChessList(String fen) {
        this.chessList = FenUtils.fenToChessList(fen);
        draw();
    }

    public void setChessList(List<Chess> list) {
        this.chessList = list;
        draw();
    }
}